package crazy_eights;

import java.util.Vector;

///////////////////////////////////////////////////////////////////////////////
/// @class Deck Deck.java <crazy_eights\Deck>
///	@brief A deck of cards
/// @details This class represents a deck of cards.
/// @note This class does not check if operations will result in a \"non-standard\"
///		deck.  For example: more than 52 cards, card duplicates.
/// @warning Operations that attempt to modify an empty deck will result
///		in an exception being thrown.
///////////////////////////////////////////////////////////////////////////////
public class Deck {

	///////////////////////////////////////////////////////////////////////////
	/// @brief Cards in the Deck.
	///////////////////////////////////////////////////////////////////////////
	private Vector<Card> cards;
	
	///////////////////////////////////////////////////////////////////////////
	/// @brief Constructor
	/// @note The Deck will be ordered.
	/// @Warning REQUIRES: None
	/// @see reset()
	///////////////////////////////////////////////////////////////////////////
	public Deck()
	{
		cards = new Vector<Card>();
		reset();
	}
	
	///////////////////////////////////////////////////////////////////////////
	/// @brief Is the Deck empty
	/// @Warning REQUIRES: None
	///////////////////////////////////////////////////////////////////////////
	public Boolean isEmpty()
	{
		return cards.isEmpty();
	}
	
	///////////////////////////////////////////////////////////////////////////
	/// @brief Peeks at the top card
	/// @details This function duplicates and returns the top Card.
	/// @note This function does not modify the Deck.
	/// @warning REQUIRES: None
	///////////////////////////////////////////////////////////////////////////
	public Card peekTop() throws Exception
	{
		if(cards.isEmpty())
		{
			throw new Exception("Deck empty - cannot peek at top!");
		}
		return new Card(cards.firstElement());
	}
	
	///////////////////////////////////////////////////////////////////////////
	/// @brief Removes and returns the top card in the deck
	/// @details This function is similar to pop, where it removes the card
	///		from the top and returns it.
	/// @warning REQUIRES:
	///		@li The Deck to be non-empty. Throws Exception.
	///////////////////////////////////////////////////////////////////////////
	public Card getTop() throws Exception
	{
		if(cards.isEmpty())
		{
			throw new Exception("Deck empty - cannot get top!");
		}
		Card c = cards.firstElement();
		cards.remove(0);
		return c;
	}
	
	///////////////////////////////////////////////////////////////////////////
	/// @brief Resets the Deck
	/// @details This function resets the Deck to 52 cards, ordered Ace to Two
	///		and suite order: Spades, Hearts, Clubs, Diamonds.
	/// @warning REQUIRES: None
	///////////////////////////////////////////////////////////////////////////	
	public void reset()
	{
		cards.clear();
		AddSuiteToDeck(Card.Suite.SPADES);
		AddSuiteToDeck(Card.Suite.HEARTS);
		AddSuiteToDeck(Card.Suite.CLUBS);
		AddSuiteToDeck(Card.Suite.DIAMONDS);
	}
	
	///////////////////////////////////////////////////////////////////////////
	/// @brief Adds an ordered suite to the end of the Deck
	/// @details Adds the given suite type to the end of the Deck, in the order
	///		of Ace to Two.
	/// @attention This function does not check if the Deck will become \"invalid\".
	///		In other words, the size of the Deck could exceed 52 and duplicates
	///		of cards could result.
	///////////////////////////////////////////////////////////////////////////
	private void AddSuiteToDeck(Card.Suite suite)
	{
		cards.add(new Card(Card.Value.ACE, suite));
		cards.add(new Card(Card.Value.KING, suite));
		cards.add(new Card(Card.Value.QUEEN, suite));
		cards.add(new Card(Card.Value.JACK, suite));
		cards.add(new Card(Card.Value.TEN, suite));
		cards.add(new Card(Card.Value.NINE, suite));
		cards.add(new Card(Card.Value.EIGHT, suite));
		cards.add(new Card(Card.Value.SEVEN, suite));
		cards.add(new Card(Card.Value.SIX, suite));
		cards.add(new Card(Card.Value.FIVE, suite));
		cards.add(new Card(Card.Value.FOUR, suite));
		cards.add(new Card(Card.Value.THREE, suite));
		cards.add(new Card(Card.Value.TWO, suite));
	}
}
